package com.ww.exercise.coroutine.mid.q11

import kotlinx.coroutines.*
import kotlinx.coroutines.sync.Semaphore
import kotlinx.coroutines.sync.withPermit
import kotlin.random.Random
import kotlin.system.measureTimeMillis

// 订单数据类
data class Order(
    val id: String,
    val amount: Double,
    val status: String
)

// 订单处理结果
data class OrderResult(
    val orderId: String,
    val success: Boolean,
    val retryCount: Int,
    val totalTimeMillis: Long,
    val lastErrorMessage: String? = null
)

// 统计报告
data class StatisticsReport(
    val totalOrders: Int,
    val successCount: Int,
    val failedCount: Int,
    val averageTimeMillis: Double,
    val maxRetries: Int
)

// 模拟订单处理服务（可能会失败）
class OrderProcessingService {
    // 模拟出来订单，随机失败
    suspend fun processOrder(order: Order): Boolean {
        // 模拟网络请求耗时
        delay(Random.nextLong(500, 1500))
        // 30%的概率处理失败，模拟网络波动
        return Random.nextDouble() > 0.3
    }
}

// 订单处理器
class OrderProcessor(
    private val service: OrderProcessingService,
    private val maxConcurrency: Int,
    private val maxRetries: Int
) {
    private val semaphore = Semaphore(maxConcurrency)

    // 处理单个订单，带重试机制
    private suspend fun processSingleOrder(order: Order): OrderResult {
        var retryCount = 0
        var lastError: String? = null
        val totalTime = measureTimeMillis {
            while (retryCount < maxRetries) {
                try {
                    // 使用信号量控制并发
                    val success = semaphore.withPermit {
                        service.processOrder(order)
                    }

                    if (success) {
                        return@measureTimeMillis
                    } else {
                        retryCount++
                        lastError = "处理失败，准备重试"
                    }
                } catch (e: Exception) {
                    retryCount++
                    lastError = e.message ?: "未知错误"
                }

                // 如果还能重试，等待后重试
                if (retryCount < maxRetries) {
                    val delayTime = 1000L * (1 shl (retryCount - 1))
                    delay(delayTime)
                }
            }
        }

        return OrderResult(
            order.id,
            success = retryCount < maxRetries,
            retryCount = retryCount,
            totalTimeMillis = totalTime,
            lastErrorMessage = if (retryCount >= maxRetries) lastError else null
        )
    }

    // 批量处理订单
    suspend fun processOrders(orders: List<Order>): Pair<List<OrderResult>, StatisticsReport> = coroutineScope {
        // 启动协程处理所有订单
        val results = orders.map { order ->
            async(Dispatchers.IO) {
                processSingleOrder(order)
            }
        }.awaitAll()

        // 生成统计报告
        val stats = generateStatistics(results)
        Pair(results, stats)
    }

    // 生成统计报告
    private fun generateStatistics(results: List<OrderResult>): StatisticsReport {
        val total = results.size
        val successCount = results.count { it.success }
        val failedCount = total - successCount
        val totalTime = results.sumOf { it.totalTimeMillis }
        val averageTime = totalTime.toDouble() / total
        val maxRetries = results.maxOf { it.retryCount }

        return StatisticsReport(
            totalOrders = total,
            successCount = successCount,
            failedCount = failedCount,
            averageTimeMillis = averageTime,
            maxRetries = maxRetries
        )
    }
}

fun main() = runBlocking {
    // 1.创建1000个测试订单
    val orders = (1..1000).map {
        Order(
            id = "ORDER-${it}",
            amount = 100.0 + Random.nextDouble() * 900.0,
            status = "PENDING"
        )
    }

    // 2.初始化处理器（最大并发50，最多重试3次）
    val processor = OrderProcessor(
        service = OrderProcessingService(),
        maxConcurrency = 50,
        maxRetries = 3
    )

    // 3.处理所有订单并计时
    val totalProcessingTime = measureTimeMillis {
        val (results, stats) = processor.processOrders(orders)

        println("===== 订单处理统计报告 =====")
        println("总订单数: ${stats.totalOrders}")
        println("成功数: ${stats.successCount} (${"%.2f".format(stats.successCount * 100.0 / stats.totalOrders)}%)")
        println("失败数: ${stats.failedCount} (${"%.2f".format(stats.failedCount * 100.0 / stats.totalOrders)}%)")
        println("平均处理时间: ${"%.2f".format(stats.averageTimeMillis)} ms")
        println("最大重试次数: ${stats.maxRetries}")
        println("===========================")

        // 5.打印部分结果示例（前10个订单）
        println("\n部分订单处理结果示例：")
        results.take(10).forEach {
            val status = if (it.success) "成功" else "失败"
            println("订单 ${it.orderId}: $status, 重试次数: ${it.retryCount}, 耗时: ${it.totalTimeMillis}ms")
        }
    }

    println("\n总处理时间：${totalProcessingTime}ms")
}